home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / byteibm.arc / PERPROPC.C < prev    next >
C/C++ Source or Header  |  1985-07-12  |  20KB  |  594 lines

  1. /* 
  2.                   LISTING 1 - AN EXAMPLE FEATURES TABLE
  3. */
  4.  
  5. /* 
  6.    This code contains a C language Features Table which contains the location 
  7.    and copyright string that uniquely identify a machine.  In addition to the
  8.    copyrights, the bit fields for the  FEATURES and  VIDEO_FEATURES variables
  9.    are defined. Note that this code is compiled with the Lattice  C  Compiler
  10.    version 2.15, using -md -n options.  Copyright  (c)  1986  Dan Jacobs  and 
  11.    Joel Rosenblum for public, unrestricted use.
  12. */
  13.  
  14. /* bit flags for FEATURES */
  15.  
  16. #define IBMPC       0x0100  /* IBM PC, XT, Portable, */
  17. #define IBMPCAT     0x0200  /* IBM AT */
  18. #define IBMCOMPAT   0x0400  /* IBM PC BIOS Compatible */
  19. #define IBM_CONVERT 0x0800  /* IBM Convertible */
  20. #define GENERIC     0x1000  /* Assumed Generic PC */
  21. #define NO_DMA      0x2000  /* Machine has no DMA */
  22. #define WANG        0x4000  /* Wang PC Special Case*/
  23. #define TIPROF      0x8000  /* TI Professional PC Special Case */
  24. #define CPU_88      0x0001  /* 8088, 8086 Processor */
  25. #define CPU_186     0x0002  /* 80188, 80186 Processor */ 
  26. #define CPU_286     0x0004  /* 80286 Processor */
  27. #define CPU_V20     0x0008  /* V20, V30 Processor */        
  28. #define NDP         0x0010  /* 8087, 80287 Math Co-processor */
  29.  
  30. /* bit flags for VIDEO_FEATURES */
  31.  
  32. #define CGA         0x0001  /* IBM Color Graphics Adapter */
  33. #define MONO        0x0002  /* IBM Monochrome Adapter */
  34. #define HERCULES    0x0004  /* Hercules Monochrome Adapter Card */
  35. #define PGA         0x0008  /* IBM Professional Graphics Adapter */
  36. #define EGA_MONO    0x0010  /*  w/Monochrome Monitor */
  37. #define EGA_COLOR   0x0020  /*  w/Color Monitor */
  38. #define EGA_HIGH    0x0040  /*  w/High Resolution Color Monitor */
  39. #define UNKNOWN     0x0080  /* Unknown Graphics Type */
  40. #define ANSI        0x0100  /* ANSI.SYS installed */
  41.  
  42. /* Additional bit fields may also be defined, please see TABLE 1 for suggestions */
  43.  
  44. struct machine_info {
  45.     char    *logo;  /* Unique copyright string */
  46.     long    addr;   /* String memory location  */
  47.             /* Note: actually (char *) must be (long) to pass lattice C */
  48.     int type;   /* Machine attributes */
  49. } feature_table[] = {
  50.  
  51. /*      copyright notice, physical address, pctype */
  52.  
  53.     { "IBM", 0xFE00EL, IBMPC|IBMCOMPAT},    /* All IBMs */
  54.     { "COMPAQ", 0xFFFEAL, IBMCOMPAT},       /* All COMPAQs */
  55.     { "Corona", 0xFE00F, IBMCOMPAT},        /* Old Version Corona */
  56.     { "Corona", 0xFE01A, IBMCOMPAT},        /* Version 3.10 ROM Corona (also Phillips) */
  57.     { "M.P.C.", 0xFDB2D, IBMCOMPAT},        /* New Columbia */
  58.     { "Columbia", 0xFF768, IBMCOMPAT},      /* Old Columbia */
  59.     { "Eagle PC", 0xFFFAA, IBMCOMPAT},      /* Eagle PC */
  60.     { "Eagle PC", 0xFF810, IBMCOMPAT},      /* Eagle PC Plus */
  61.     { "Zenith", 0xFB000, IBMCOMPAT},        /* Zenith Data Systems */
  62.     { "Zenith", 0xFC2FF, GENERIC},          /* Zenith 100 */
  63.     { "MITSUBISHI", 0xFC02A, IBMCOMPAT},    /* Sperry PC and Leading Edge */
  64.     { "TVS", 0xFE003, IBMCOMPAT},           /* Televideo */
  65.     { "OSM", 0xFFFF5, IBMCOMPAT},           /* OSM Rom Version 3.6 or later */
  66.     { "OLIVETTI", 0xFC050, IBMCOMPAT},      /* AT&T-IS PC6300 and Xerox  */
  67.                                             /* NOTE: AT&T is not supporting V1.0 ROMs */
  68.     { "WANG", 0xFFFC2, WANG|GENERIC},       /* WANG professional */
  69.     { "ADDS", 0xFC050, IBMCOMPAT},          /* Applied Data Digital Systems Model PC/I */
  70.     { "CROS", 0xFE000, IBMCOMPAT},          /* Seattle Telecom Turbo Boards */
  71.     { "PCPI", 0xFE00F, IBMCOMPAT},          /* Personal Computer Products */
  72.     { "TAVA", 0xFE018, IBMCOMPAT},          /* Tava PC */
  73.     { "Tandy", 0xFC02B, IBMCOMPAT|NO_DMA},  /* Tandy 1000 has no DMA unless memory upgrade board installed */
  74.     { "Tandon", 0xFC013, IBMCOMPAT},        /* Tandy 1200 */
  75.     { "Texas", 0xFE022, TIPROF},            /* TI Professional V1.23 & V2.11 SYSROM */
  76.     { "American", 0xFE004, IBMCOMPAT},      /* American PC lookalike */
  77.     { "STD", 0xFE00EL, IBMCOMPAT},          /* STD Turbo Boards in IBMs */
  78.     { "STD", 0xFFFEAL, IBMCOMPAT},          /* STD Turbo Boards in COMPAQs */
  79.     { "TOMCAT", 0xFE028, IBMCOMPAT},        /* Tomcat AT clone */
  80.     { "WYSE", 0xFC003, IBMCOMPAT},          /* WYSE PC BIOS Version 1.08 */
  81.     { "Hewlett-Packard", 0xF0024, IBMCOMPAT}, /* Hewlett-Packard Vectra AT Compatible */
  82.     { "Morrow", 0xFE073, IBMCOMPAT},        /* Morrow Pivot II & Zenith 171 Desktops */
  83.  
  84.     /* Additional machines are added to the list starting here */
  85.  
  86.     { NULL, NULL, 0}
  87. };
  88.  
  89. -------------------------------------------------------------------------------
  90.  
  91. /*
  92.           LISTING 2 - DETERMINING MACHINE COMPATIBILITY
  93. */
  94.  
  95. /* 
  96.    This code shows  how the Features Table is used to set up
  97.    the bit flags  in the FEATURES  variable.  Once  FEATURES
  98.    is  set  for  the  current  machine,  your  other program 
  99.    modules can  use it to  determine what  section  of  code 
  100.    should be executed to yield the best program performance.
  101.  
  102.    Copyright (c) 1986 Dan Jacobs and Joel Rosenblum
  103.  
  104.    Compiled using Lattice C ver 2.15, using -md -n options
  105. */
  106.  
  107. unsigned int video_features;   /* global variable which holds video attributes */
  108.  
  109. unsigned int set_features()
  110. {
  111.     char *cp;                   /* Pointer */
  112.     struct machine_info *p;     /* Features Table Structure */
  113.     unsigned int feature;       /* FEATURES bit field variable */ 
  114.  
  115.     /* Assume the PC is generic to start */
  116.     feature = GENERIC;          /* default to generic */
  117.  
  118. /*
  119.    A psuedo code example of how to override the automatic set of FEATURES 
  120.    assuming that either a slash option  or an DOS environment variable is 
  121.    set.   Your actual code will depend upon how you do the parsing.   See
  122.    the  section  on  "using the  machine's  copyright notice to determine
  123.    compatibility" in our text.
  124.  
  125. begin pseudo code example --
  126.  
  127.     if ((/IBM entered on command line) |
  128.         (compatibility = IBM is in the environment)) {
  129.         feature = IBMCOMPAT;
  130.         goto cpu_test;      
  131.     }   
  132. -- end psudo code example */
  133.  
  134.     for (p = feature_table; p->addr != NULL; p++) /* if next table entry is NULL, then end loop */
  135.         if (strncmp((char *) p->addr, p->logo, strlen(p->logo)) == 0) {
  136.             feature = p->type;
  137.             break;
  138.         }
  139.  
  140.     if (feature & IBMPC) {         /* IBM Personal Computers */
  141.         cp = (char *) 0xFFFFE;      /* physical address 0FFFF:E */
  142.         switch (*cp) {
  143.             case 0xF9:  /* IBM Convertible */
  144.                 feature |= IBM_CONVERT;
  145.                 break;
  146.             case 0xFC:      /* IBM AT */
  147.                 feature |= IBMPCAT | CPU_286;
  148.                 break;
  149.             case 0xFD:  /* IBM PC JR */
  150.                 feature |= NO_DMA;
  151.                 break;
  152.             case 0xFE:  /* IBM XT or Portable */
  153.             case 0xFF:  /* IBM PC */
  154.                 break;
  155.             default:
  156.                 break;  /* unknown IBM type */
  157.         }
  158.     }
  159.  
  160.     /* add the cpu type to FEATURES -- see listing 3 */
  161.     feature = cputest(feature);
  162.     
  163.     /* check for numeric data processor -- see listing 4 */
  164.     feature = test_ndp(feature);
  165.  
  166.     /* add the video display type to VIDEO_FEATURES -- see listing 6 */
  167.     video_features = video_test(feature);
  168.  
  169.     /* check if  ANSI.SYS is present -- see listing 7 */
  170.     if (check_ansi()) {
  171.         video_features |= ANSI;
  172.     } else {
  173.         putch(0x0D);  /* this cleans up any garbage left on the screen */
  174.         putch(' ');   /* by the ansi check if ANSI.SYS  is not present */       
  175.         putch(' ');
  176.         putch(' ');
  177.         putch(' ');
  178.         putch(0x0A);
  179.         putch(0x0D);
  180.     }
  181.  
  182.     return (feature);
  183. }
  184.  
  185. _______________________________________________________________________________
  186.  
  187. /*
  188.     LISTING 5B - ILLUSTRATION OF TIMING DELAYS, C CALLING ROUTINE
  189. */
  190.  
  191. /*
  192.    This driver provides an example of how to use  cal.asm  for 
  193.    delay calibrate routines.  The routine will print the delay
  194.    according to the speed  of the processor.   The  closer you
  195.    make the loops to your actual code,  the more  accurate the
  196.    calculation will be.   You should  then adjust  your actual
  197.    program delay proportional to the results of this test.
  198. */
  199.  
  200. #include <stdio.h>
  201.  
  202. static char id[] = "#PROGRAM: calibrate driver (hzm)";
  203.  
  204. /*
  205.  * Global variables:
  206.  */
  207.  
  208.     int    us500;
  209.     int    ms2;
  210. /*
  211.  *  init -- calibrate the delay counters
  212.  */
  213.  
  214. static
  215. init()
  216. {
  217.     us500 = delaycal(500);
  218.     ms2   = delaycal(2000);
  219.     printf("%d loops equals 500 microseconds.\n", us500);
  220.     printf("%d loops equals 2 milliseconds.\n", ms2);
  221. }
  222.  
  223. /*
  224.  *  delay1 -- delay for .5 sec (= 1000 * 500 usec)
  225.  */
  226.  
  227. static
  228. delay1()
  229. {
  230.     char    before[4];
  231.     char    after[4];
  232.     int    i;
  233.  
  234.     printf("\nNow, delay 1000 * 500 usec...\n");
  235.     dostime(&before);
  236.     for (i = 0; i < 1000; i++) del500u();
  237.     dostime(&after);
  238.     printf("  Start: %02d:%02d:%02d.%02d\n",
  239.         before[1], before[0], before[3], before[2]);
  240.     printf("  End:   %02d:%02d:%02d.%02d\n",
  241.         after[1], after[0], after[3], after[2]);
  242. }
  243.  
  244. /*
  245.  *  delay2 -- delay for 4.0 sec (= 2000 * 2000 usec)
  246.  */
  247.  
  248. static
  249. delay2()
  250. {
  251.     char    before[4];
  252.     char    after[4];
  253.     int    i;
  254.  
  255.     printf("\nNow, delay 2000 * 2000 usec...\n");
  256.     dostime(&before);
  257.     for (i = 0; i < 2000; i++) del2m();
  258.     dostime(&after);
  259.     printf("  Start: %02d:%02d:%02d.%02d\n",
  260.         before[1], before[0], before[3], before[2]);
  261.     printf("  End:   %02d:%02d:%02d.%02d\n",
  262.         after[1], after[0], after[3], after[2]);
  263. }
  264.  
  265. /*
  266.  * driver main program:
  267.  */
  268.  
  269. main(argc, argv)
  270. int argc; char *argv[];
  271. {
  272.     init();
  273.     delay1();
  274.     delay2();
  275.     exit(0);
  276. }
  277.  
  278. -------------------------------------------------------------------------------
  279.  
  280. /*
  281.                 LISTING 7 - TEST FOR PRESENCE OF ANSI.SYS
  282. */
  283.  
  284. /*
  285.    This code contains the check for the presence of ANSI.SYS.   If
  286.    found, the appropriate bit in VIDEO_FEATURES is set.  This code
  287.    is called from listing 2 and is  compatible with the  Lattice C
  288.    Compiler.
  289.  
  290.    Copyright (c) 1986 Dan Jacobs and Joel Rosenblum
  291.  
  292.    Compiled using Lattice C ver 2.15, using -md -n options
  293. */
  294.  
  295. #include "dos.h"
  296.  
  297. #define FAIL  1
  298. #define OK    0
  299.  
  300. #define ANSI     1
  301. #define NOT_ANSI 0
  302.  
  303. int line, line2, column, column2;
  304. union REGS in, out;     /* defined in dos.h file of Lattice C Compiler */
  305.  
  306. /****************************************************************************
  307.  
  308. NAME
  309.     check_ansi
  310.  
  311. SYNOPSIS
  312.     Checks to see if ANSI.SYS is installed on your machine
  313.     by doing an ansi "report cursor position"  call  twice 
  314.     in a row to make sure each call returns a value,   and
  315.     that the values match for  two successive calls.   For
  316.     further  information  on  ANSI.SYS,  see  the  IBM DOS  
  317.     technical reference.
  318.  
  319. RETURN VALUE
  320.     1 if ansi.sys is installed
  321.     0 otherwise 
  322.  
  323. *****************************************************************************/
  324.  
  325. check_ansi()
  326. {
  327.  
  328.     dump_key_buffer();
  329.     cputs("\x1B[6n");   /* report cursor position command */
  330.     if (get_line_column()) {
  331.         dump_key_buffer();
  332.         return NOT_ANSI;    /* no cursor position came in */
  333.     }
  334.     line2 = line;       /* save the reported values */
  335.     column2 = column;
  336.  
  337.     dump_key_buffer();
  338.     cputs("\x1B[6n");   /* try it one more time */
  339.     if (get_line_column()) {
  340.         dump_key_buffer();
  341.         return NOT_ANSI;
  342.     }
  343.  
  344.     dump_key_buffer();
  345.  
  346.     if (line2 != line || column2 != column) return NOT_ANSI;
  347.  
  348.     return ANSI;
  349. }
  350.  
  351. /***************************************************************************
  352.  
  353. NAME
  354.         get_line_column
  355.             
  356. SYNOPSIS
  357.         checks to see if there are two keystokes
  358.         the keyboard buffer (K.B.) and if so,
  359.         them in the global variables line
  360.         column.
  361.  
  362. ****************************************************************************/
  363.  
  364. get_line_column()
  365.  
  366. {
  367.     if (!(line = check_key())) return FAIL;
  368.     if (!(column = check_key())) return FAIL;
  369.     return OK;
  370. }
  371.  
  372. /***************************************************************************
  373.  
  374. NAME
  375.          check_key
  376.             
  377. SYNOPSIS
  378.         returns keystroke left in K.B. if a keystroke exists there
  379.  
  380. ****************************************************************************/
  381.  
  382.  
  383. check_key()
  384. {
  385.     int c;
  386.         
  387.     for (c = 0; c < 100; c++)
  388.          ; /* do nothing but wait */
  389.  
  390.     in.h.dl = 0xFF;
  391.     in.h.ah = 0x6;
  392.     c = intdos(&in, &out);
  393.  
  394.     if (c & 0x40) return 0;
  395.     return (int)out.h.al;
  396. }
  397.  
  398. /***************************************************************************
  399.  
  400. NAME
  401.         dump_key_buffer
  402.                     
  403. SYNOPSIS
  404.         clears K.B.
  405.  
  406. ****************************************************************************/
  407.  
  408.  
  409. dump_key_buffer()
  410. {
  411.     in.h.dl = 0xFF;
  412.     in.h.al = 0x06;
  413.     in.h.ah = 0x0C;
  414.     intdos(&in, &out);
  415. }
  416.  
  417. -------------------------------------------------------------------------------
  418.  
  419. /*
  420.            LISTING 8 - EXAMPLE VIDEO CHARACTER OUTPUT ROUTINE
  421. */
  422.  
  423. /*
  424.      This code contains a C language example that uses the bit
  425.      fields contained within the FEATURES variable to determine
  426.      if it is possible to display the IBM extended character
  427.      set on the machine.  We assume these characters may be
  428.      displayed if the machine is IBMCOMPAT.  Note that this
  429.      may be called from other modules in your program without
  430.      regard to hardware considerations.
  431.  
  432.      Copyright (c) 1986 Dan Jacobs and Joel Rosenblum
  433.  
  434.      Compiled using Lattice C ver 2.15, using -md -n options
  435. */
  436.  
  437. extern unsigned int features;       /* see definition */
  438.  
  439. /* position of characters in box_char */
  440. #define TOP_LEFT        0
  441. #define TOP_SIDE        1
  442. #define TOP_RIGHT       2
  443. #define SIDES           3
  444. #define BOTTOM_LEFT     4
  445. #define BOTTOM_SIDE     5
  446. #define BOTTOM_RIGHT    6
  447.  
  448. char box_char[2][7] =  {
  449.         {0xDA, 0xC4, 0xBF, 0xB3, 0xC0, 0xC4, 0xD9}, /* expanded char codes */
  450.         {0x2B, 0x2D, 0x2B, 0x7C, 0x2B, 0x2D, 0x2D}  /* replacement char codes
  451.                                                        to use when no extended
  452.                                                        codes can be used */     
  453.    };
  454.  
  455. /*****************************************************************************
  456.  
  457. NAME
  458.            draw_box 
  459.  
  460. SYNOPSIS
  461.            Draws a box of size, length, and width at the row 
  462.            and column specified.   Notice how the characters 
  463.            used  for  the  box  are  changed  based  on  the 
  464.            availability  of  the   extended   set.    (Those 
  465.            characters only exist on IBM compatibles).
  466.  
  467. *****************************************************************************/
  468.  
  469. draw_box(row, column, length, depth)
  470. int row, column, length, depth;
  471. {
  472.     int i;
  473.     int char_set;   /* tells  which row  of  box_char  to  use  based 
  474.                        on the the IBMCOMPAT bit  in features, use row
  475.                        0, which contains extended chars, if IBMCOMPAT
  476.                        otherwise, use  row 1 which  contains standard 
  477.                        ASCII replacements for the extended set */
  478.  
  479.     char_set = features & IBMCOMPAT ? 0 : 1;   
  480.  
  481.     move_cursor(row, column);   /* First, draw left corner */
  482.  
  483.     /* Move_curser is in listing 9.  It moves the cursor to row, column
  484.        by determining the machine's video features contained in the bit 
  485.        flags in FEATURES.   You notice that your  program does not need 
  486.        to worry about the details  of how to move the  cursor depending
  487.        upon which machine is used.   That leaves you free to solve more 
  488.        important problems */
  489.  
  490.  
  491.     putchars(box_char[char_set][TOP_LEFT], 1); 
  492.  
  493.     /* Putchars is a routine which puts the char passed in the first  arg
  494.        out to the screen the number of times specified by the second arg.
  495.        Putchar also decides which method it will use to  output that char
  496.        based on the type of equiptment  installed on your  machine.   See  
  497.        listing 9 for move_cursor detail */
  498.     
  499.     move_cursor(row, column+1);    /* now the top side */
  500.     putchars(box_char[char_set][TOP_SIDE], length-2);
  501.     
  502.     move_cursor(row, column+length-1); /* next top right corner */
  503.     putchars(box_char[char_set][TOP_RIGHT], 1);
  504.  
  505.     for(i = 1; i < length-1; i++)  {  /* Vertical sides */
  506.         move_cursor(row+i, column);
  507.         putchars(box_char[char_set][SIDES], 1);
  508.         move_cursor(row+i, column+length-1);
  509.         putchars(box_char[char_set][SIDES], 1);
  510.     }
  511.  
  512.     move_cursor(row+length-1, column); /* bottom left corner */
  513.     putchars(box_char[char_set][BOTTOM_LEFT], 1);
  514.  
  515.     move_cursor(row+length-1, column+1 ); /* bottom side */
  516.     putchars(box_char[char_set][BOTTOM_SIDE], length-2);
  517.     
  518.     move_cursor(row+length-1, column+length-1); /* bottom right corner */
  519.     putchars(box_char[char_set][BOTTOM_RIGHT], 1);
  520.  
  521. }
  522.  
  523. -------------------------------------------------------------------------------
  524.  
  525. /*
  526.           LISTING 9 - EXAMPLE VIDEO CURSOR POSITIONING ROUTINE
  527. */
  528.  
  529. /*
  530.     This routine handles the details of  cursor positioning  based on
  531.     the bits set in the variables  FEATURES and  VIDEO_FEATURES.   It 
  532.     is called from the draw_box routine in listing 8, and illustrates
  533.     how common machine dependent routines  should  be written.   Note
  534.     a similar type of routine  should exist in your program to handle
  535.     bit-mapped graphics-related calls.
  536.  
  537.    Compiled using Lattice C ver 2.15, using -md -n options
  538. */
  539.  
  540. extern unsigned int features;       /* global variable which holds machine features */
  541. extern unsigned int video_features; /* global variable which holds video-related features */
  542.  
  543.  
  544. char *screen_buff; /* pointer to buffer of 2000 (80*25) chars which is big
  545.                       enough to hold the ASCII  charactures for a complete
  546.                       video page */  
  547. char *screen_pos;  /* pointer into screen_buff at current cursor position */
  548.  
  549. char page_no;      /* previously set video page number */
  550.  
  551. char string[80];   /* string to use for ASCII calls */
  552.  
  553. /****************************************************************************
  554.  
  555. NAME
  556.     move_cursor
  557.  
  558. SYNOPSIS
  559.     moves the cursor to row, column on the video  display
  560.     note  that  the  routine decides which method to  use 
  561.     based on bits set in both FEATURES and VIDEO_FEATURES   
  562.  
  563.  
  564. *****************************************************************************/
  565.  
  566. move_cursor(row, column)
  567. int row, column;
  568. {
  569.     union REGS inregs, outregs;           /* defined in dos.h */
  570.  
  571.     if (features & IBMCOMPAT) {           /* use int 10 video bios */
  572.         inregs.h.ah = 2;                  /* set cursor position */
  573.         inregs.h.dl = column;
  574.         inregs.h.dh = row;
  575.         inregs.h.bh = page_no;            /* page number */
  576.         int86(0x10, &inregs, &outregs);      /* do bios int 10 */
  577.     } else if (video_features & ANSI) {   /* need to do ansi calls */
  578.         sprintf(string, "\x1B[%d;%df$", ++row, ++column);
  579.         dos_puts(string); /* dos_puts is a routine that calls dos and
  580.                              prints string using function 9, print string */
  581.     } else { /* dos generic mode */
  582.         screen_pos = screen_buff + row * 80 + column;         
  583.     }  
  584.  
  585.         /* NOTE: In DOS generic mode we keep a buffer (screen_buff) 
  586.            big enough to hold one video page of ASCII text.  In all 
  587.            of the calls that write to video, we move the chars into
  588.            screen_buf at the pheudo cursor position, screen_pos.
  589.            When we have completed updating the memory-based page,
  590.            we write the ASCII chars from the memory buffer to the 
  591.            actual screen using standard dos calls */ 
  592. }
  593.  
  594.